﻿using System;
using System.Linq.Expressions;

namespace Wheels
{
    public static class NewException
    {
#pragma warning disable 1591

        private static Exception smNullException = null;

        internal static string RetrieveArgumentName(this Expression<Func<object>> argument)
        {
            if (null == argument)
                return null;

            var member = argument.Body as MemberExpression;
            if (null != member)
                return member.Member.Name;

            var param = argument.Body as ParameterExpression;
            if (null != param)
                return param.Name;

            return null;
        }

        #region return new

        #region ArgumentException

        public static ArgumentException Argument(string argument, string message = null)
        {
            if (null == argument)
            {
                if (null == message)
                    return new ArgumentException();
                else
                    return new ArgumentException(message);
            }
            else
            {
                if (null == message)
                    return new ArgumentException(new ArgumentException().Message, argument);
                else
                    return new ArgumentException(message, argument);
            }
        }

        public static ArgumentException Argument(Expression<Func<object>> argument, string message = null)
        {
            return Argument(argument.RetrieveArgumentName(), message);
        }

        #endregion

        #region ArgumentNullException

        public static ArgumentNullException ArgumentNull(string argument, string message = null)
        {
            if (null == argument)
            {
                if (null == message)
                    return new ArgumentNullException();
                else
                    return new ArgumentNullException(message, smNullException);
            }
            else
            {
                if (null == message)
                    return new ArgumentNullException(argument);
                else
                    return new ArgumentNullException(argument, message);
            }
        }

        public static ArgumentNullException ArgumentNull(Expression<Func<object>> argument, string message = null)
        {
            return ArgumentNull(argument.RetrieveArgumentName(), message);
        }

        #endregion

        #region ArgumentOutOfRangeException

        public static ArgumentOutOfRangeException ArgumentOutOfRange(string argument, string message = null)
        {
            if (null == argument)
            {
                if (null == message)
                    return new ArgumentOutOfRangeException();
                else
                    return new ArgumentOutOfRangeException(message, smNullException);
            }
            else
            {
                if (null == message)
                    return new ArgumentOutOfRangeException(argument);
                else
                    return new ArgumentOutOfRangeException(argument, message);
            }
        }

        public static ArgumentOutOfRangeException ArgumentOutOfRange(Expression<Func<object>> argument, string message = null)
        {
            return ArgumentOutOfRange(argument.RetrieveArgumentName(), message);
        }

        public static ArgumentOutOfRangeException ArgumentOutOfRange(string argument, object actualValue, string message)
        {
            if (null == message)
                message = new ArgumentOutOfRangeException().Message;

            return new ArgumentOutOfRangeException(argument, actualValue, message);
        }

        public static ArgumentOutOfRangeException ArgumentOutOfRange(Expression<Func<object>> argument, object actualValue, string message)
        {
            if (null == message)
                message = new ArgumentOutOfRangeException().Message;

            return new ArgumentOutOfRangeException(argument.RetrieveArgumentName(), actualValue, message);

            //return ArgumentOutOfRange(argument.RetrieveArgumentName(), actualValue, message);
        }

        #endregion

        #endregion
    }
}
